import tkinter as tk
import numpy as np

# 循环(递归)神经网络（输入层大小，隐藏层大小，输出层大小，输入，上一个隐藏层）
def rnn(input_size, hidden_size, output_size, input, prev):
    global w_x, w_h, w_y, b_h, b_y
    # 初始化权重和偏置
    w_x = np.random.rand(hidden_size, input_size)
    w_h = np.random.rand(hidden_size, hidden_size)
    w_y = np.random.rand(output_size, hidden_size)
    b_h = np.random.rand(hidden_size)
    b_y = np.random.rand(output_size)
    return forward(input, prev, input_size, hidden_size, output_size)
# 随机生成数组1
def array1(size, n=0.0):
    return np.random.rand(size)
# 随机生成数组2
def array2(rows, cols, n=0.0):
    return np.random.rand(rows, cols)

# 激活函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# 前向传播（输入，上一个隐藏层，输入层大小，隐藏层大小，输出层大小）
def forward(input, prev, input_size, hidden_size, output_size):
    # 隐藏层
    h = np.zeros(hidden_size)
    # 隐藏层的计算
    for i in range(hidden_size):
        sum = 0
        for j in range(input_size):
            # 输入层的权重
            sum += input[j] * w_x[i][j]
        # 隐藏层的权重
        for k in range(hidden_size):
            sum += prev[k] * w_h[i][k]
        # 隐藏层的偏置
        sum += b_h[i]
        # 激活函数
        h[i] = sigmoid(sum)
    # 输出层
    y = np.zeros(output_size)
    # 输出层的计算
    for i in range(output_size):
        sum = 0
        # 隐藏层的权重
        for j in range(hidden_size):
            sum += h[j] * w_y[i][j]
        sum += b_y[i]
        y[i] = sigmoid(sum)
    return [h, y]

# 开始计算
def send():
    # 获取输入数据并转浮点数
    input = txt.get().split(',')
    inputs = [float(val) for val in input]
    # 输入数据的大小
    size = len(inputs)
    # 隐藏层和输出层的大小
    hidden_size = 5
    output_size = 2
    prev = array1(hidden_size, 0)
    # 开始计算
    arr = rnn(size, hidden_size, output_size, inputs, prev)
    box.insert(tk.END, f'隐藏值 {arr[0]}\n输出值 {arr[1]}')

root = tk.Tk()
root.title('循环(递归)神经网络')
root.geometry('500x150')
# 初始化数据
w_x = 0
w_h = 0
w_y = 0
b_h = 0
b_y = 0
label = tk.Label(root, text='归一后的输入数据')
label.pack()

txt = tk.Entry(root)
txt.insert(0, '0.1,0.2,0.3,0.4,0.5')
txt.pack(fill=tk.X)

button = tk.Button(root, text='识别', command=send)
button.pack()

box = tk.Text(root, height=5)
box.pack(fill=tk.X)

root.mainloop()